package org.kernely.stream.utils;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.HashSet;
import java.util.Set;

import org.kernely.security.dao.UserDetailsDAO;
import org.kernely.security.persistence.Role;
import org.kernely.security.persistence.User;
import org.kernely.security.persistence.UserDetails;
import org.kernely.stream.StreamBundle;
import org.kernely.stream.dao.MessageDAO;
import org.kernely.stream.persistence.Message;
import org.kernely.ui.mvp.KernelyEventSender;
import org.kernely.ui.utils.KernelyDialogWindow;
import org.kernely.ui.utils.KernelyNotification;

import com.vaadin.Application;
import com.vaadin.terminal.ExternalResource;
import com.vaadin.terminal.FileResource;
import com.vaadin.terminal.ThemeResource;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Embedded;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.themes.Reindeer;

public class MessageComponent extends VerticalLayout implements KernelyEventSender {

	/** Generated serial version */
	private static final long serialVersionUID = 8967959828180807108L;
	private Button deleteButton;
	private Button favButton;
	private Message message; // The message displayed.
	private HorizontalLayout buttonsLayout;
	private boolean isFavorite = false;
	private HorizontalLayout messageLayout;
	
	/**
	 * Creates a panel displaying message informations.
	 * @param message The message to display
	 * @param application A reference on the application, to display image
	 * @param isComment Set to true if the message is a comment, false otherwise
	 */
	public MessageComponent(Message message, Application application, boolean isComment) {
		this.messageLayout = new HorizontalLayout();
		this.message = message;
		messageLayout.setStyleName("messagelayout");
		buttonsLayout = new HorizontalLayout();
		buttonsLayout.setSpacing(true);


		// Writer infos
		UserDetails details = UserDetailsDAO.getInstance().getUserDetails(message.getUser());

		//Date
		SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
		SimpleDateFormat dateHourFormat = new SimpleDateFormat("kk:mm:ss");

		Label messageContent;
		if (! isComment){
			messageContent = new Label(
				"<span style=\"font-weight:bold;\">"+message.getStream().getTitle()+"</span><br/>"
				+ message.getContent()+"<br/>"
				+"<span style=\"font-style:italic;color:grey\">From "+details.getFirstname()+" "+details.getName()+", the "+dateFormat.format(message.getDate())+" at "+dateHourFormat.format(message.getDate())+".</span>",Label.CONTENT_XHTML);
		}
		else{
			messageContent = new Label(message.getContent()+"<br/>"
					+"<span style=\"font-style:italic;color:grey\">From "+details.getFirstname()+" "+details.getName()+", the "+dateFormat.format(message.getDate())+" at "+dateHourFormat.format(message.getDate())+".</span>",Label.CONTENT_XHTML);
		}

		// Set the image
		Embedded imageEmbedded = new Embedded();
		if (details.getImage() == null || details.getImage().equals("")){
			// Default images are located in src/main/resources/VAADIN/themes/kernelytheme/img
			if (details.getCivility() == 0){
				ThemeResource imageResource = new ThemeResource("img/default_male.png");
				imageEmbedded.setSource(imageResource);
			}
			else {
				ThemeResource imageResource = new ThemeResource("img/default_female.png");
				imageEmbedded.setSource(imageResource);
			}
		} else {
			File imageFile = new File("/tmp/uploads/"+details.getImage());
			if (imageFile != null){
				FileResource imageResource = new FileResource(imageFile, application);
				imageEmbedded.setSource(imageResource);	        	
			}
		}        
		imageEmbedded.setHeight(40, UNITS_PIXELS);
		imageEmbedded.setWidth(40, UNITS_PIXELS);
		
		// Favorites button, not visible if the message is a comment
		if (! isComment){
			favButton = new Button();
			User current = StreamBundle.getSecurityService().getCurrentUser();
			for (User u : this.message.getFavoriteUsers()){
				if (u.equals(current)){
					isFavorite = true;
				}
			}
			if (isFavorite){
				messageLayout.setStyleName("favoritelayout");

				favButton.setIcon(new ExternalResource("streambundle/images/fav_16*16.png"));
			} else {
				favButton.setIcon(new ExternalResource("streambundle/images/unfav_16*16.png"));
			}
			favButton.setStyleName(Reindeer.BUTTON_LINK);
			favButton.setSizeUndefined();
			favButton.addListener(new ClickListener() {

				/**
				 * Action called when the button is clicked.
				 */
				public void buttonClick(ClickEvent event) {
					updateFavorite();
				}
			});
			
			buttonsLayout.addComponent(favButton);
		}
		
		// Delete button, only for users which correct rights
		if (StreamBundle.getSecurityService().currentUserHasOneOf(Role.ROLE_ADMINISTRATOR)
				|| StreamBundle.getSecurityService().currentUserHasPermission(
						message.getStream().getCategory() + ":deletemessages:" + message.getStream().getUid())){
			deleteButton = new Button();
			deleteButton.setIcon(new ThemeResource("img/cancel_icon16*16.png"));
			deleteButton.setStyleName(Reindeer.BUTTON_LINK);

			deleteButton.setSizeUndefined();
			deleteButton.addListener(new Button.ClickListener() {
				/** Action when the delete button is clicked. */
				public void buttonClick(ClickEvent event) {
					deleteProcess();
				}
			});
			buttonsLayout.addComponent(deleteButton);
		}
		
		
		HorizontalLayout leftLayout = new HorizontalLayout();
		leftLayout.setSpacing(true);
		leftLayout.setSizeUndefined();
		leftLayout.addComponent(imageEmbedded);
		leftLayout.addComponent(messageContent);
		messageLayout.addComponent(leftLayout);
		messageLayout.addComponent(buttonsLayout);
		messageLayout.setComponentAlignment(buttonsLayout, Alignment.TOP_RIGHT);
		messageLayout.setSizeFull();
		this.addComponent(messageLayout);
		this.addComponent(new Label("<hr/>",Label.CONTENT_XHTML));
				
		this.setSizeFull();
	}

	/**
	 * Creates a panel displaying message informations. By default, the message is a message (and not a comment).
	 * @param message The message to display.
	 * @param application A reference on the application, to display image.
	 */
	public MessageComponent(Message message, Application application) {
		this(message, application, false);
	}

	/**
	 * Process to delete a message, with confirm dialog and notification.
	 */
	private void deleteProcess(){
		boolean isAdmin = StreamBundle.getSecurityService().currentUserHasOneOf(Role.ROLE_ADMINISTRATOR);
		String permission = "Streams/Users:deletemessages:"+message.getStream().getUid();
		boolean canDelete = StreamBundle.getSecurityService().currentUserHasPermission(permission);

		final Window window = getWindow();

		// Delete the message if the user have rights.
		if (isAdmin || canDelete){

			// Confirm window
			final KernelyDialogWindow confirm = new KernelyDialogWindow(
					"Kernely - Delete message", "Do you really want to delete this message ?",
					KernelyDialogWindow.ASKING_ICON);
			confirm.setConfirmButtonCaption("Yes");
			confirm.setCancelButtonCaption("No");

			// Adding listeners on window's "confirm" buttons click
			confirm.getConfirmButton().addListener(new Button.ClickListener() {
				/**
				 * The action when the "Yes" button is clicked
				 */
				public void buttonClick(ClickEvent event) {
					MessageDAO mdao = MessageDAO.getInstance();
					
					// TODO TO IMPROVE THAT WITH DELETE_ORPHAN CASCADE TYPE !!
					for(Message m : mdao.getAllCommentsFromMessage(message)){
						mdao.deleteMessage(m);
					}
					
					// Disable the user in the database
					mdao.deleteMessage(message);
					window.removeWindow(confirm);

					// Remove the confirm window
					window.showNotification(new KernelyNotification("Message deleted.", KernelyNotification.INFO_ICON));

					//Inform the user
					deleteMessageFromUI();
				}
			});

			window.addWindow(confirm);
		}
	}

	private void deleteMessageFromUI(){
		VerticalLayout container = (VerticalLayout) this.getParent();
		// Remove the component from UI
		container.removeComponent(this);
	}
	
	/**
	 * Add the current message to the favorites of the user.
	 */
	private void updateFavorite(){
		Message message = MessageDAO.getInstance().findMessageById(this.message.getId());
		// Check if the message still exists
		if (message == null){
			getWindow().showNotification(new KernelyNotification("An error occured. The message can't be added to the favorites, because an user have deleted it.", KernelyNotification.ERROR_ICON));
		}
		else {
			Set<User> users = message.getFavoriteUsers();
			if (users == null){
				users = new HashSet<User>();
			}
			if (isFavorite){
				// The message is no longer considered as a favorite
				users.remove(StreamBundle.getSecurityService().getCurrentUser());
				favButton.setIcon(new ExternalResource("streambundle/images/unfav_16*16.png"));
				this.isFavorite = false;
				messageLayout.setStyleName("messagelayout");
			} else {
				// The message is now considered as a favorite
				users.add(StreamBundle.getSecurityService().getCurrentUser());
				favButton.setIcon(new ExternalResource("streambundle/images/fav_16*16.png"));
				this.isFavorite = true;
				messageLayout.setStyleName("favoritelayout");
			}
			this.message.setFavoriteUsers(users);
			MessageDAO.getInstance().updateMessage(message);

		}
	}
	
}
